package com.zhoug.mpchart.renderer;

import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.Log;

import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.BarBuffer;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.model.GradientColor;
import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.zhoug.mpchart.MPChartConfig;

/**
 * @Author: zhoug
 * @Date: 2024-07-26
 * @Description:
 */
public class MPHorizontalBarChartRenderer  extends HorizontalBarChartRenderer {
    private static final String TAG = ">>>MPHBarChartRenderer";
    private static final boolean DEBUG = MPChartConfig.DEBUG;
    /**
     * 是否启用圆弧顶部
     */
    private boolean arcEnable = false;

    public MPHorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
        super(chart, animator, viewPortHandler);
    }

    public MPHorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, boolean arcEnable) {
        super(chart, animator, viewPortHandler);
        this.arcEnable = arcEnable;
    }
    private RectF mBarShadowRectBuffer = new RectF();
    private RectF arcRect = new RectF();//柱子顶部圆弧
    private RectF dataRect = new RectF();//柱子
    private Path mPath = new Path();

    @Override
    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
//        super.drawDataSet(c,dataSet,index);
        Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());

        mBarBorderPaint.setColor(dataSet.getBarBorderColor());
        mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));

        final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f;

        float phaseX = mAnimator.getPhaseX();
        float phaseY = mAnimator.getPhaseY();

        // draw the bar shadow before the values
        if (mChart.isDrawBarShadowEnabled()) {
            mShadowPaint.setColor(dataSet.getBarShadowColor());

            BarData barData = mChart.getBarData();

            final float barWidth = barData.getBarWidth();
            final float barWidthHalf = barWidth / 2.0f;
            float x;

            for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount());
                 i < count;
                 i++) {

                BarEntry e = dataSet.getEntryForIndex(i);

                x = e.getX();

                mBarShadowRectBuffer.top = x - barWidthHalf;
                mBarShadowRectBuffer.bottom = x + barWidthHalf;

                trans.rectValueToPixel(mBarShadowRectBuffer);

                if (!mViewPortHandler.isInBoundsTop(mBarShadowRectBuffer.bottom))
                    continue;

                if (!mViewPortHandler.isInBoundsBottom(mBarShadowRectBuffer.top))
                    break;

                mBarShadowRectBuffer.left = mViewPortHandler.contentLeft();
                mBarShadowRectBuffer.right = mViewPortHandler.contentRight();

                c.drawRect(mBarShadowRectBuffer, mShadowPaint);
            }
        }

        // initialize the buffer
        BarBuffer buffer = mBarBuffers[index];
        buffer.setPhases(phaseX, phaseY);
        buffer.setDataSet(index);
        buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
        buffer.setBarWidth(mChart.getBarData().getBarWidth());

        buffer.feed(dataSet);

        trans.pointValuesToPixel(buffer.buffer);

        final boolean isSingleColor = dataSet.getColors().size() == 1;

        if (isSingleColor) {
            mRenderPaint.setColor(dataSet.getColor());
        }
        //每个柱子的点数
        int barPointCount = buffer.size() / dataSet.getEntryCount();
        if (DEBUG) {
            Log.d(TAG, "drawDataSet:barPointCount=" + barPointCount);
        }
        for (int j = 0; j < buffer.size(); j += 4) {

            if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3]))
                break;

            if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1]))
                continue;

            if (!isSingleColor) {
                // Set the color for the currently drawn value. If the index
                // is out of bounds, reuse colors.
                mRenderPaint.setColor(dataSet.getColor(j / 4));
            }
            //开始
            if (dataSet.getGradientColor() != null) {
                GradientColor gradientColor = dataSet.getGradientColor();
                mRenderPaint.setShader(
                        new LinearGradient(
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j+2],
                                buffer.buffer[j + 1],
                                gradientColor.getStartColor(),
                                gradientColor.getEndColor(),
                                Shader.TileMode.MIRROR));
            }
            if (dataSet.getGradientColors() != null) {
                mRenderPaint.setShader(
                        new LinearGradient(
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j+2],
                                buffer.buffer[j + 1],
                                dataSet.getGradientColor(j / 4).getStartColor(),
                                dataSet.getGradientColor(j / 4).getEndColor(),
                                Shader.TileMode.MIRROR));
            }
            //柱子位置
            dataRect.left = buffer.buffer[j];
            dataRect.top = buffer.buffer[j + 1];
            dataRect.right = buffer.buffer[j + 2];
            dataRect.bottom = buffer.buffer[j + 3];
            //堆叠图只绘制最上面一个的顶部圆弧
            //第一个需要绘制顶部圆弧的开始位置
            int barIndex = j / barPointCount + 1;
            int startDrawTopIndex = barIndex * barPointCount - 4;
            if (DEBUG) {
                Log.d(TAG, "drawDataSet:barIndex=" + barIndex + ",startDrawTopIndex=" + startDrawTopIndex + ",j=" + j);
            }
            if (arcEnable && j == startDrawTopIndex) {
                float offset = dataRect.bottom - dataRect.top;
                float h = dataRect.right - dataRect.left;
                if (DEBUG) {
                    Log.d(TAG, "drawDataSet:offset=" + offset + ",h=" + h);
                }
                if (h < offset) {
                    offset = h;
                }
                arcRect.left = dataRect.right-offset;
                arcRect.right = dataRect.right;
                arcRect.top = dataRect.top;
                arcRect.bottom = dataRect.bottom ;
                mPath.reset();

                mPath.moveTo(arcRect.left, arcRect.bottom);
                mPath.lineTo(dataRect.left, arcRect.bottom);
                mPath.lineTo(dataRect.left, dataRect.top);
                mPath.lineTo(arcRect.left, arcRect.top);

                mPath.arcTo(arcRect, -90, 180, false);
                c.drawPath(mPath, mRenderPaint);

            } else {
                c.drawRect(dataRect, mRenderPaint);
            }

            if (drawBorder) {
                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                        buffer.buffer[j + 3], mBarBorderPaint);
            }
        }

    }


    /**
     * 是否启用圆弧顶部
     *
     * @param arcEnable
     */
    public void setArcEnable(boolean arcEnable) {
        this.arcEnable = arcEnable;
    }

}
